/**
  ******************************************************************************
  * @file    mg_driver_i2c_master.c
  * @author  
  * @version V1.1
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2020 Shanghai Macrogiga Electronics</center></h2>
  *
  ******************************************************************************
  */

#include "mg_driver_i2c.h"
#include "mg_driver_clock.h"

void I2C_Init(I2C_TypeInitDef* I2C_InitStruct)
{
	//u16 tmpreg = 0;
    CLK_SetClockGate(CLK_GATE_I2C_EN);
	
    I2C->I2C_ENABLE = 0;
	
	//tmpreg = I2C->I2C_CON;
    I2C->I2C_CON = I2C_InitStruct->I2C_Speed | I2C_InitStruct->I2C_Mode  | I2C_RESTART_EN | I2C_SLAVE_ENABLE;
    I2C->I2C_TAR = I2C_InitStruct->I2C_Addr; //7 bit format only
	I2C->I2C_SAR = I2C_InitStruct->I2C_Addr;
	
	//only test,add calc from system clock
	switch (I2C_InitStruct->I2C_Speed)
	{
		case I2C_SPEED_FAST:
			I2C->I2C_FS_SCL_HCNT = 0x002C;
			I2C->I2C_FS_SCL_LCNT = 0x002C;
			break;
			
		case I2C_SPEED_STANDARD:
		default:
			I2C->I2C_SS_SCL_HCNT = 0x00BE;
			I2C->I2C_SS_SCL_LCNT = 0x00BE;
			break;
	}
	
	I2C->I2C_INTR_MASK = 0;
	I2C->I2C_RX_TL = 0x0;
	I2C->I2C_TX_TL = 0x0;
}

void I2C_Cmd(FunctionalState NewState)
{
	I2C->I2C_ENABLE = NewState;
}

void I2C_GenerateSTOP(void)
{
	I2C->I2C_DATA_CMD = 0x0200;
}

void I2C_GeneralCallCmd(FunctionalState NewState)
{
	if (NewState != DISABLE)
	{
		I2C->I2C_TAR |= 0x0800;
	}
	else
	{
		I2C->I2C_TAR &= 0xf7ff;
	}
}

void I2C_ITConfig(u16 I2C_IT,FunctionalState NewState)
{
	if (I2C_RX_FULL == I2C_IT)
	{
		I2C->I2C_DATA_CMD = I2C_READ;
	}
	
	if (NewState != DISABLE)
	{
		I2C->I2C_INTR_MASK |= I2C_IT;
	}
	else
	{
		I2C->I2C_INTR_MASK &= ~I2C_IT;
	}
}

u16 I2C_GetEvent(void)
{
	return I2C->I2C_RAW_INTR_STAT;
}

ITStatus I2C_GetITStatus(u16 I2C_IT)
{
	if (I2C->I2C_RAW_INTR_STAT & I2C_IT)
	{
		return SET;
	}
	else
	{
		return RESET;
	}
}

void I2C_ClearIT(u16 I2C_IT)
{
	if(I2C_IT & I2C_RX_UNDER)	{I2C->I2C_CLR_RX_UNDER;}
    if(I2C_IT & I2C_RX_OVER)	{I2C->I2C_CLR_RX_OVER;}
    if(I2C_IT & I2C_TX_OVER) 	{I2C->I2C_CLR_TX_OVER;}
    if(I2C_IT & I2C_RD_REQ) 	{I2C->I2C_CLR_RD_REQ;}
    if(I2C_IT & I2C_TX_ABRT) 	{I2C->I2C_CLR_TX_ABRT;}
    if(I2C_IT & I2C_RX_DONE) 	{I2C->I2C_CLR_RX_DONE;}
    if(I2C_IT & I2C_ACTIVITY)	{I2C->I2C_CLR_ACTIVITY;}
    if(I2C_IT & I2C_STOP_DET)	{I2C->I2C_CLR_STOP_DET;}
    if(I2C_IT & I2C_START_DET)	{I2C->I2C_CLR_START_DET;}
    if(I2C_IT & I2C_GEN_CALL)	{I2C->I2C_CLR_GEN_CALL;} 
}

void I2C_SendData(u8 const Data)
{
	I2C->I2C_DATA_CMD = I2C_WRITE | Data;
	while(!(I2C->I2C_STATUS & I2C_STATUS_TFE));
}

void I2C_SendDataAndStop(u8 const Data)
{
	I2C->I2C_DATA_CMD = I2C_STOP | I2C_WRITE | Data;
	while(!(I2C->I2C_STATUS & I2C_STATUS_TFE));
}

u8 I2C_ReceiveData(void)
{
	I2C->I2C_DATA_CMD = I2C_READ;
	while(!(I2C->I2C_STATUS & I2C_STATUS_RFNE));
	return (u8)I2C->I2C_DATA_CMD;
}

u8 I2C_ReceiveDataAndStop(void)
{
	I2C->I2C_DATA_CMD = I2C_STOP | I2C_READ;
	while(!(I2C->I2C_STATUS & I2C_STATUS_RFNE));
	return (u8)I2C->I2C_DATA_CMD;
}

void I2C_SendBuf(u8 const *Buf,u8 const Len)
{
	u16 cnt;
	
	for(cnt=0;cnt<Len;cnt++)
	{
		if (cnt==Len)
		{
			I2C->I2C_DATA_CMD = I2C_STOP | *(Buf+cnt);
		}
		else
		{
			I2C->I2C_DATA_CMD = *(Buf+cnt);
		}
		while(!(I2C->I2C_STATUS & I2C_STATUS_TFNF));
	}
}

void I2C_ReceiveBuf(u8 *Buf,u8 const Len)
{
	u16 cntw=0,cntr=0;
	
	do
	{
		if (cntw < Len)//send command
		{
			if (!(I2C->I2C_STATUS&I2C_STATUS_RFF))
			{
				I2C_ClearIT(I2C_RX_OVER);
				I2C->I2C_DATA_CMD = I2C_READ;
				cntw++;
			}
		}
		
		if (I2C->I2C_STATUS & I2C_STATUS_RFNE)//receive data
		{
			*(Buf+cntr) = (u8)I2C->I2C_DATA_CMD;
			I2C_ClearIT(I2C_RX_FULL);
			cntr++;
			
		}
	}
	while(cntr<Len);
}
